#ifndef MEMORYMANAGER_H
#define MEMORYMANAGER_H

#include "BitOps.h"
#include "LRU.h"

#ifndef NULL
#define NULL 0						/* NULL, we bow down and worship you. */
#endif

#define NO_MORE_MEMORY 16385		/*some error codes*/
#define INVALID_INPUT 16386			

#define RAM_SIZE 1048576			/* The size of RAM in bytes. */
#define BS_SIZE 67108864			/* The size of BACKING STORE in bytes. */
#define FRAME_SIZE 4096				/* The size of a frame in bytes. */
#define NUM_SYSTEM_FRAMES 56		/* The number of system frames set aside for the OS. */
#define NUM_PAGETABLES 100			/* The max number of page tables allowed by the OS. */
#define BS_FRAMES BS_SIZE/FRAME_SIZE
#define SWAP_SIZE (RAM_SIZE/FRAME_SIZE) - NUM_SYSTEM_FRAMES

unsigned char backingstore[BS_SIZE];			/* Array representing the backing store*/
unsigned char ram[RAM_SIZE];					/* Array representing the ram */

unsigned short int pagetable[BS_FRAMES];	/*The actual pagetable*/
unsigned short int swaptable[SWAP_SIZE];	/*Swaptable - what's where in RAM*/

int allocatedPages;					/* The number of pages that have been allocated by the memory manager */

/***
 * Initializes the pagetable array and some memory manager tools
 * @author Jan Durakiewicz
 */
void init_pagetable();

/***
 * Gets the next free page in the page table
 * @author Jan Durakiewicz
 * @return an address, or NO_MORE_MEMORY constant
*/
short unsigned int get_next_free();

/***
 * Allocates a page table if possible
 * @author Jan Durakiewicz
 * @param the size, in frames, of the page table to be created
 * @return a page table ID, or NO_MORE_MEMORY constant
 */
short unsigned int alloc_pt(int size);

/***
 * Deallocates a page table
 * @author Jan Durakiewicz
 * @param the page table ID to be deallocated
 */
void dealloc_pt(int ptid);

/***
 * Extends a page table by one frame
 * @author Jan Durakiewicz
 * @param the page table ID to be extended
 * @return the address of the last page in the table before alloc (probably)
 */
short unsigned int extend_pagetable(int ptid);

/***
 * Allocates some memory for a process
 * @author Daniel Fairweather
 * @param ptid The page table ID of the caller
 * @param size The size in bytes of the space to be allocated
 */
int alloc_m(int ptid, int size);
int dealloc_m(int ptid, int size);
int readBlockHeader(int ptid, int index);

/***
 * Translates a virtual address into a physical one
 * @author Jan Durakiewicz
 * @param ptid The page table ID of the caller
 * @param v_address The virtual address to be translated
 * @return Physical address, or -1 if the virtual address is out of bounds
 */
int get_physical_address(int ptid, int v_address);

/***
 * Writes a character to a specified location in memory
 * NO INPUT CHECKING
 * @author Jan Durakiewicz
 * @param ptid The page table ID of the caller
 * @param v_address the virtual address to write to
 * @param to_write Char to write to memory
 */
void write_to_virtual(int ptid, int v_address, char to_write);

/***
 * Reads a character from the specified location in memory
 * NO INPUT CHECKING
 * @author Jan Durakiewicz
 * @param ptid Page table ID for caller
 * @param v_address the virtual address to read from
 * @return The char at the specified location
 */
unsigned char read_from_virtual(int ptid, int v_address);

#endif